From 3a455ed8f95324bdbf554935f7cff87518665c39 Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Fri, 22 Oct 2010 10:38:21 +0200 Subject: [PATCH] GtkStyleSet: Register the border-style and border-color properties This is also implemented in the theming engine, although the default CSS should be using it in order to theme buttons, troughs, sliders and such. --- gtk/gtkenums.h | 6 + gtk/gtkstyleset.c | 3 + gtk/gtkthemingengine.c | 292 +++++++++++++++++++++-------------------- 3 files changed, 161 insertions(+), 140 deletions(-) diff --git a/gtk/gtkenums.h b/gtk/gtkenums.h index 85c8c561ae..99a52cf394 100644 --- a/gtk/gtkenums.h +++ b/gtk/gtkenums.h @@ -618,6 +618,12 @@ typedef enum { GTK_JUNCTION_RIGHT = 1 << 3 } GtkJunctionSides; +typedef enum { + GTK_BORDER_STYLE_NONE, + GTK_BORDER_STYLE_SOLID, + GTK_BORDER_STYLE_INSET, + GTK_BORDER_STYLE_OUTSET +} GtkBorderStyle; G_END_DECLS diff --git a/gtk/gtkstyleset.c b/gtk/gtkstyleset.c index 9aa5519ec7..a53a75c314 100644 --- a/gtk/gtkstyleset.c +++ b/gtk/gtkstyleset.c @@ -23,6 +23,7 @@ #include #include +#include "gtktypebuiltins.h" #include "gtkstyleprovider.h" #include "gtkstyleset.h" #include "gtkprivate.h" @@ -92,6 +93,8 @@ gtk_style_set_class_init (GtkStyleSetClass *klass) gtk_style_set_register_property ("border-width", G_TYPE_INT, NULL, NULL); gtk_style_set_register_property ("border-radius", G_TYPE_INT, NULL, NULL); + gtk_style_set_register_property ("border-style", GTK_TYPE_BORDER_STYLE, NULL, NULL); + gtk_style_set_register_property ("border-color", GDK_TYPE_COLOR, NULL, NULL); gtk_style_set_register_property ("background-image", CAIRO_GOBJECT_TYPE_PATTERN, NULL, NULL); gtk_style_set_register_property ("border-image", GTK_TYPE_9SLICE, NULL, NULL); diff --git a/gtk/gtkthemingengine.c b/gtk/gtkthemingengine.c index f91f1c323a..b7e101bbd0 100644 --- a/gtk/gtkthemingengine.c +++ b/gtk/gtkthemingengine.c @@ -52,7 +52,8 @@ enum { SIDE_LEFT = 1, SIDE_BOTTOM = 1 << 1, SIDE_RIGHT = 1 << 2, - SIDE_TOP = 1 << 3 + SIDE_TOP = 1 << 3, + SIDE_ALL = 0xF }; struct GtkThemingEnginePrivate @@ -1139,25 +1140,97 @@ color_shade (const GdkColor *color, } static void -_cairo_round_rectangle (cairo_t *cr, - gdouble radius, - gdouble x, - gdouble y, - gdouble width, - gdouble height) +_cairo_round_rectangle_sides (cairo_t *cr, + gdouble radius, + gdouble x, + gdouble y, + gdouble width, + gdouble height, + guint sides, + GtkJunctionSides junction) { radius = CLAMP (radius, 0, MIN (width / 2, height / 2)); - if (radius == 0) - cairo_rectangle (cr, x, y, width, height); + if (sides & SIDE_RIGHT) + { + if (radius == 0 || + (junction & GTK_JUNCTION_TOP) || + (junction & GTK_JUNCTION_RIGHT)) + cairo_move_to (cr, x + width, y); + else + { + cairo_new_sub_path (cr); + cairo_arc (cr, x + width - radius, y + radius, radius, - G_PI / 4, 0); + } + + if (radius == 0 || + (junction & GTK_JUNCTION_BOTTOM) || + (junction & GTK_JUNCTION_RIGHT)) + cairo_line_to (cr, x + width, y + height); + else + cairo_arc (cr, x + width - radius, y + height - radius, radius, 0, G_PI / 4); + } + + if (sides & SIDE_BOTTOM) + { + if (radius != 0 && + ! (junction & GTK_JUNCTION_RIGHT) && + ! (junction & GTK_JUNCTION_BOTTOM)) + { + if ((sides & SIDE_RIGHT) == 0) + cairo_new_sub_path (cr); + + cairo_arc (cr, x + width - radius, y + height - radius, radius, G_PI / 4, G_PI / 2); + } + + if (radius == 0 || + (junction & GTK_JUNCTION_BOTTOM) || + (junction & GTK_JUNCTION_LEFT)) + cairo_line_to (cr, x, y + height); + else + cairo_arc (cr, x + radius, y + height - radius, radius, G_PI / 2, 3 * (G_PI / 4)); + } else + cairo_move_to (cr, x, y + height); + + if (sides & SIDE_LEFT) + { + if (radius != 0 && + ! (junction & GTK_JUNCTION_LEFT) && + ! (junction & GTK_JUNCTION_BOTTOM)) + { + if ((sides & SIDE_BOTTOM) == 0) + cairo_new_sub_path (cr); + + cairo_arc (cr, x + radius, y + height - radius, radius, 3 * (G_PI / 4), G_PI); + } + + if (radius == 0 || + (junction & GTK_JUNCTION_TOP) || + (junction & GTK_JUNCTION_LEFT)) + cairo_line_to (cr, x, y); + else + cairo_arc (cr, x + radius, y + radius, radius, G_PI, G_PI + G_PI / 4); + } + + if (sides & SIDE_TOP) { - cairo_new_sub_path (cr); - cairo_arc (cr, x + width - radius, y + radius, radius, - G_PI / 2, 0); - cairo_arc (cr, x + width - radius, y + height - radius, radius, 0, G_PI / 2); - cairo_arc (cr, x + radius, y + height - radius, radius, G_PI / 2, G_PI); - cairo_arc (cr, x + radius, y + radius, radius, G_PI, 3 * (G_PI / 2)); - cairo_close_path (cr); + if (radius != 0 && + ! (junction & GTK_JUNCTION_TOP) && + ! (junction & GTK_JUNCTION_LEFT)) + { + if ((sides & SIDE_TOP) == 0) + cairo_new_sub_path (cr); + + cairo_arc (cr, x + radius, y + radius, radius, 5 * (G_PI / 4), 3 * (G_PI / 2)); + } + + if (radius == 0 || + (junction & GTK_JUNCTION_TOP) || + (junction & GTK_JUNCTION_RIGHT)) + cairo_line_to (cr, x + width, y); + else + cairo_arc (cr, x + width - radius, y + radius, radius, 3 * (G_PI / 2), - G_PI / 4); } } @@ -1174,9 +1247,11 @@ gtk_theming_engine_render_background (GtkThemingEngine *engine, GtkStateFlags flags; gboolean running; gdouble progress, alpha = 1; + GtkJunctionSides junction; gint radius; flags = gtk_theming_engine_get_state (engine); + junction = gtk_theming_engine_get_junction_sides (engine); cairo_save (cr); if (gtk_theming_engine_has_class (engine, "spinbutton") && @@ -1197,7 +1272,9 @@ gtk_theming_engine_render_background (GtkThemingEngine *engine, running = gtk_theming_engine_state_is_running (engine, GTK_STATE_PRELIGHT, &progress); - _cairo_round_rectangle (cr, (gdouble) radius, x, y, width, height); + _cairo_round_rectangle_sides (cr, (gdouble) radius, + x, y, width, height, + SIDE_ALL, junction); cairo_clip (cr); cairo_translate (cr, x, y); @@ -1448,163 +1525,98 @@ gtk_theming_engine_render_frame (GtkThemingEngine *engine, { GtkStateFlags flags; GdkColor lighter, darker; - GdkColor *bg_color; + GdkColor *border_color; Gtk9Slice *slice; + GtkBorderStyle border_style; + gint border_width, radius; + GtkJunctionSides junction; flags = gtk_theming_engine_get_state (engine); + junction = gtk_theming_engine_get_junction_sides (engine); gtk_theming_engine_get (engine, flags, "border-image", &slice, - "background-color", &bg_color, + "border-color", &border_color, + "border-style", &border_style, + "border-width", &border_width, + "border-radius", &radius, NULL); if (slice) { gtk_9slice_render (slice, cr, x, y, width, height); gtk_9slice_unref (slice); - gdk_color_free (bg_color); - return; } - - cairo_save (cr); - cairo_set_line_width (cr, 1); - - color_shade (bg_color, 0.7, &darker); - color_shade (bg_color, 1.3, &lighter); - - if (gtk_theming_engine_has_class (engine, "entry") || - gtk_theming_engine_has_class (engine, "scrolled-window") || - gtk_theming_engine_has_class (engine, "viewport")) + else if (border_style != GTK_BORDER_STYLE_NONE) { - gdk_cairo_set_source_color (cr, bg_color); - add_path_rectangle_sides (cr, x + 1, y + 1, width - 2, height - 2, - SIDE_BOTTOM | SIDE_RIGHT); - cairo_stroke (cr); - - cairo_set_source_rgb (cr, 0, 0, 0); - add_path_rectangle_sides (cr, x + 1, y + 1, width - 2, height - 2, - SIDE_TOP | SIDE_LEFT); - cairo_stroke (cr); - - cairo_set_source_rgb (cr, 1, 1, 1); - add_path_rectangle_sides (cr, x, y, width, height, - SIDE_BOTTOM | SIDE_RIGHT); - cairo_stroke (cr); + cairo_save (cr); - gdk_cairo_set_source_color (cr, &darker); - add_path_rectangle_sides (cr, x, y, width, height, - SIDE_TOP | SIDE_LEFT); - cairo_stroke (cr); - } - else if (gtk_theming_engine_has_class (engine, "button") && - gtk_theming_engine_has_class (engine, "default")) - { - cairo_set_source_rgb (cr, 0, 0, 0); - cairo_rectangle (cr, x + 0.5, x + 0.5, width - 1, height - 1); - cairo_stroke (cr); - } - else if (gtk_theming_engine_has_class (engine, "scrollbar") && - gtk_theming_engine_has_class (engine, "trough")) - { - gdk_cairo_set_source_color (cr, &darker); - add_path_rectangle_sides (cr, x, y, width, height, - SIDE_TOP | SIDE_LEFT); - cairo_stroke (cr); + color_shade (border_color, 0.7, &darker); + color_shade (border_color, 1.3, &lighter); - gdk_cairo_set_source_color (cr, &lighter); - add_path_rectangle_sides (cr, x, y, width, height, - SIDE_BOTTOM | SIDE_RIGHT); - cairo_stroke (cr); - } - else if (gtk_theming_engine_has_class (engine, "spinbutton")) - { - if (gtk_theming_engine_has_class (engine, "button")) + switch (border_style) { - GtkJunctionSides sides; - - sides = gtk_theming_engine_get_junction_sides (engine); + case GTK_BORDER_STYLE_NONE: + break; + case GTK_BORDER_STYLE_SOLID: + cairo_set_line_width (cr, border_width); - if (sides & GTK_JUNCTION_BOTTOM) - y += 2; - - width -= 3; - height -= 2; - - if (gtk_theming_engine_get_direction (engine) == GTK_TEXT_DIR_RTL) - x += 2; - else - x += 1; + if (border_width > 1) + { + x += (gdouble) border_width / 2; + y += (gdouble) border_width / 2; + width -= border_width; + height -= border_width; + } - gdk_cairo_set_source_color (cr, &lighter); - add_path_rectangle_sides (cr, x, y, width, height, SIDE_TOP); + _cairo_round_rectangle_sides (cr, (gdouble) radius, x, y, width, height, + SIDE_ALL, junction); + gdk_cairo_set_source_color (cr, border_color); cairo_stroke (cr); - gdk_cairo_set_source_color (cr, &darker); - add_path_rectangle_sides (cr, x, y, width, height, SIDE_BOTTOM); - cairo_stroke (cr); - } - else - { - gdk_cairo_set_source_color (cr, &lighter); - add_path_rectangle_sides (cr, x, y, width, height, - SIDE_BOTTOM | SIDE_RIGHT); - cairo_stroke (cr); + break; + case GTK_BORDER_STYLE_INSET: + case GTK_BORDER_STYLE_OUTSET: + cairo_set_line_width (cr, border_width); + cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE); - gdk_cairo_set_source_color (cr, &darker); - add_path_rectangle_sides (cr, x, y, width, height, SIDE_TOP); - cairo_stroke (cr); + if (border_width > 1) + { + gint d; - gdk_cairo_set_source_color (cr, bg_color); - add_path_rectangle_sides (cr, x, y, width - 1, height - 1, SIDE_BOTTOM); - cairo_stroke (cr); + d = border_width / 2; + x += d; + y += d; + width -= d * 2; + height -= d * 2; + } - cairo_set_source_rgb (cr, 0, 0, 0); - add_path_rectangle_sides (cr, x, y + 1, width - 1, height - 3, - SIDE_TOP | SIDE_LEFT | SIDE_RIGHT); - cairo_stroke (cr); - } - } - else - { - if (flags & GTK_STATE_FLAG_ACTIVE) - { - cairo_set_source_rgb (cr, 0, 0, 0); - add_path_rectangle_sides (cr, x + 1, y + 1, width - 2, height - 2, - SIDE_TOP | SIDE_LEFT); - cairo_stroke (cr); + if (border_style == GTK_BORDER_STYLE_INSET) + gdk_cairo_set_source_color (cr, border_color); + else + gdk_cairo_set_source_color (cr, &darker); - gdk_cairo_set_source_color (cr, &lighter); - add_path_rectangle_sides (cr, x, y, width, height, - SIDE_BOTTOM | SIDE_RIGHT); + _cairo_round_rectangle_sides (cr, (gdouble) radius, x, y, width, height, + SIDE_BOTTOM | SIDE_RIGHT, junction); cairo_stroke (cr); - gdk_cairo_set_source_color (cr, &darker); - add_path_rectangle_sides (cr, x, y, width, height, - SIDE_TOP | SIDE_LEFT); - cairo_stroke (cr); - } - else - { - gdk_cairo_set_source_color (cr, &darker); - add_path_rectangle_sides (cr, x, y, width - 1, height - 1, - SIDE_BOTTOM | SIDE_RIGHT); - cairo_stroke (cr); + if (border_style == GTK_BORDER_STYLE_INSET) + gdk_cairo_set_source_color (cr, &darker); + else + gdk_cairo_set_source_color (cr, border_color); - gdk_cairo_set_source_color (cr, &lighter); - add_path_rectangle_sides (cr, x, y, width, height, - SIDE_TOP | SIDE_LEFT); + _cairo_round_rectangle_sides (cr, (gdouble) radius, x, y, width, height, + SIDE_TOP | SIDE_LEFT, junction); cairo_stroke (cr); - cairo_set_source_rgb (cr, 0, 0, 0); - add_path_rectangle_sides (cr, x, y, width, height, - SIDE_BOTTOM | SIDE_RIGHT); - cairo_stroke (cr); + break; } - } - cairo_restore (cr); + cairo_restore (cr); + } - gdk_color_free (bg_color); + if (border_color) + gdk_color_free (border_color); } static void -- 2.30.2